package com.violet.myorm.core.foreign;

import com.violet.myorm.Model;
import com.violet.myorm.core.combination.CreateCombination;
import com.violet.myorm.core.combination.QueryCombination;
import com.violet.myorm.core.combination.DeleteCombination;
import com.violet.myorm.core.combination.UpdateCombination;
import com.violet.myorm.core.condition.LambdaWhere;
import com.violet.myorm.core.condition.SerializableFunction;
import com.violet.myorm.core.execute.Delete;
import com.violet.myorm.core.execute.Insert;
import com.violet.myorm.core.execute.Query;
import com.violet.myorm.core.execute.Update;
import com.violet.myorm.core.page.Limit;
import com.violet.myorm.core.source.Reflect;

import java.lang.reflect.Field;
import java.util.List;

// 实现一对多的 查询, 删除, 修改, 创建
public final class ManyForeign<E>
    implements
        Relation<List<E>>,
        QueryCombination<E, ManyForeign<E>>,
        DeleteCombination<E, ManyForeign<E>>,
        UpdateCombination<E, ManyForeign<E>>,
        CreateCombination<ManyForeign<E>>
{
    private List<E> data;
    private final String foreign;
    private final Object key;
    private final Class<E> clazz;

    private final Query<E> query;
    private final Delete<E> delete;
    private final Update<E> update;

    private Insert<E> insert;

    private void initWhere() {
        LambdaWhere<E> eq = new LambdaWhere<E>().eq(foreign, key);
        query.where(eq);
        delete.where(eq);
        update.where(eq);
    }

    private ManyForeign(Class<E> clazz, String foreign, Object key) {
        delete = new Delete<>(clazz);
        update = new Update<>(clazz);
        query = new Query<>(clazz);

        initWhere();

        this.foreign = foreign;
        this.key = key;
        this.clazz = clazz;
    }

    @Override
    public List<E> getData() {
        if (data == null) data = executeQuery();
        return data;
    }

    @Override
    public ManyForeign<E> fields(SerializableFunction<E, ?>... fields) {
        query.fields(fields);
        return this;
    }

    @Override
    public Limit<E> limit(int page, int size) {
        return query.limit(page, size);
    }

    @Override
    public ManyForeign<E> where(LambdaWhere<E> condition) {
        condition.andEq(foreign, key);
        query.where(condition);
        delete.where(condition);
        update.where(condition);
        return this;
    }

    @Override
    public int count() {
        return query.count();
    }

    @Override
    public List<E> executeQuery() {
        return query.executeQuery();
    }

    @Override
    public int executeDelete() {
        int i = delete.executeDelete();
        initWhere();
        return i;
    }

    public int setNull() {
        return new Update<>(clazz)
            .where(new LambdaWhere<E>().eq(foreign, key))
            .set(foreign, null)
            .executeUpdate();
    }

    @Override
    public <T> ManyForeign<E> set(SerializableFunction<E, ?> function, T value) {
        update.set(function, value);
        return this;
    }

    @Override
    public ManyForeign<E> set(String fieldName, Object value) {
        update.set(fieldName, value);
        return this;
    }

    @Override
    public int executeUpdate() {
        int i = update.executeUpdate();
        initWhere();
        return i;
    }

    @Override
    public ManyForeign<E> insert(Model... entities) {
        insert = new Insert<>(clazz);
        Field field = Reflect.getFieldByName(clazz, foreign);
        for (Model entity : entities) {
            try {
                field.set(entity, key);
                insert.insert(entity);
            }
            catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return this;
    }

    @Override
    public int executeCreate() {
        return insert.executeCreate();
    }
}
